use std::cell::OnceCell;
use std::sync::OnceLock;

use tauri::Wry;

static mut INSTANCE: OnceLock<Application> = OnceLock::new();

pub(crate) fn application() -> &'static Application {
    unsafe { INSTANCE.get_or_init(|| Application::default()) }
}

pub(crate) fn application_mut() -> &'static mut Application {
    unsafe {
        INSTANCE.get_mut().unwrap_or_else(|| {
            INSTANCE.set(Application::default()).expect("初始化全局应用失败");
            INSTANCE.get_mut().unwrap()
        })
    }
}

/// 快捷方法
pub(crate) fn app() -> &'static tauri::AppHandle<Wry> {
    application().app()
}

/// 快捷方法
pub(crate) fn window() -> Option<&'static tauri::Window> {
    application().window()
}

#[derive(Default, Debug, Clone)]
pub(crate) struct Application {
    app_handler: OnceCell<tauri::AppHandle<Wry>>,
    main_window: Option<tauri::Window>,
}

impl Application {
    /// 初始化应用处理器对象
    pub(crate) fn init_app(&mut self, app: tauri::AppHandle<Wry>) {
        self.app_handler.set(app).expect("无法设置应用处理器");
    }

    /// 设置全局主窗口对象
    pub(crate) fn set_window(&mut self, window: Option<tauri::Window>) {
        self.main_window = window;
    }

    /// 获取应用处理器对象
    pub(crate) fn app(&self) -> &tauri::AppHandle<Wry> {
        self.app_handler.get().expect("无法获取应用处理器")
    }

    /// 获取主窗口对象
    pub(crate) fn window(&self) -> Option<&tauri::Window> {
        self.main_window.as_ref()
    }
}